package org.phalanx.client.net;

import java.awt.Color;


import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.phalanx.client.PhalanxClient;
import org.phalanx.client.UI.PhalanxPanelManager;
import org.phalanx.client.dialogs.MainMenuPanel;
import org.phalanx.client.dialogs.PhalanxOnlineStatusPanel;
import org.phalanx.client.properties.ClientPreferences;

public class XMPPConnectionManager implements ChatManagerListener, MessageListener {
	private static final Integer STATUS_CONNECTING = 1;
	private static final Integer STATUS_ONLINE = 2;
	private static final Integer STATUS_OFFLINE = 3;
	private static final Integer STATUS_INCOMPLETE_CRED = 4;
	private static final Integer STATUS_BAD_PW = 5;
	private static final Integer STATUS_BAD_HOST = 6;
	private static final Integer STATUS_ERROR = 7;
	private static final Integer STATUS_DISCONNECTED = 8;
	private ConnectionConfiguration xmppConfig;
	private XMPPConnection xmppCon;
	private boolean isConnected = false;
	
	public XMPPConnectionManager(){
	}
	
	public void init(){
		setStatus(STATUS_CONNECTING);
		if (!checkIfCredentialsExist()){
			setStatus(STATUS_INCOMPLETE_CRED);
		}else{
			configureXMPPConnection();
			if (this.connectToXMPPServer()){
				isConnected = true;
				this.setStatus(STATUS_ONLINE);
				this.setConnectionState();
				this.manageSession();
			}
		}
		this.setDisconnectionState();
		isConnected = false;
	}
	
	private boolean checkIfCredentialsExist(){
		boolean isExist = false;
		ClientPreferences c = PhalanxClient.getClientInstance().getPreferences();
		
		if (c.getProperties("PhalanxClient.XMPPClient.XMPPServerHost") != null &&
				c.getProperties("PhalanxClient.XMPPClient.Username") != null){
			isExist = true;
		}
		
		return isExist;
	}
	
	private void configureXMPPConnection(){
		ClientPreferences c = PhalanxClient.getClientInstance().getPreferences();
		String serverName = c.getProperties("PhalanxClient.XMPPClient.XMPPServerHost");
		Integer port = c.getPropertiesAsInt("PhalanxClient.XMPPClient.XMPPServerPort", 5222);
		String domain = c.getProperties("PhalanxClient.XMPPClient.Domain", serverName);
		Boolean compression = c.getPropertiesAsBoolean("PhalanxClient.XMPPClient.Compression", false);
		
		xmppConfig = new ConnectionConfiguration(serverName, port, domain);
		xmppConfig.setCompressionEnabled(compression);
		xmppConfig.setReconnectionAllowed(false);
	}
	
	private boolean connectToXMPPServer(){
		boolean isConnected = false;
		
		ClientPreferences c = PhalanxClient.getClientInstance().getPreferences();
		String userName = c.getProperties("PhalanxClient.XMPPClient.Username");
		String password = c.getProperties("PhalanxClient.XMPPClient.Password", "");
		String resource = "PhalanxClient";

		try {
			xmppCon = new XMPPConnection(xmppConfig);
			xmppCon.connect();

			xmppCon.login(userName, password,resource);

			if (!xmppCon.isAuthenticated()){
				setStatus(STATUS_BAD_PW);
			}else{
				isConnected = true;
			}
		}  catch (XMPPException xe){
			// TODO: Look to set up detailed errors for now just general
			setStatus(STATUS_ERROR);
		}
		
		return isConnected;
	}
	
	private void manageSession(){
/*		ChatManager listenForConnections = xmppCon.getChatManager();
		listenForConnections.addChatListener(new PhalanxConnectionListener());*/
		
		while (xmppCon.isConnected()){
			try {
				Thread.sleep(50);
			} catch (InterruptedException ie){
				ie.printStackTrace();
			}
		}
		this.setStatus(STATUS_DISCONNECTED);
		this.setDisconnectionState();
	}
	
	public void processMessage(Chat arg0, Message arg1) {
		// TODO Auto-generated method stub
		
	}

	public void chatCreated(Chat arg0, boolean arg1) {
		// TODO Auto-generated method stub

	}
	
	private void setStatus(int StatusNumber){
		String message = "";
		PhalanxOnlineStatusPanel statusPanel = (PhalanxOnlineStatusPanel)PhalanxPanelManager.getInstance().getPanel(PhalanxOnlineStatusPanel.NAME);

		if (StatusNumber == STATUS_CONNECTING){
			statusPanel.setStatusText("Connecting to Server",Color.white);
		}
		else if (StatusNumber == STATUS_ONLINE){
			statusPanel.setStatus(true);
		}
		else if (StatusNumber == STATUS_OFFLINE){
			statusPanel.setStatus(false);
		}
		else if (StatusNumber == STATUS_INCOMPLETE_CRED){
			statusPanel.setStatusText("Login Info Incomplete. Please go to preferences and check your Login info", Color.red);
			try {
				Thread.sleep(5000);
			} catch (InterruptedException ie){}
			statusPanel.setStatus(false);
		}
		else if (StatusNumber == STATUS_BAD_PW){
			statusPanel.setStatusText("Incorrect username or Password. Please make sure your login credentials are correct", Color.red);
			try {
				Thread.sleep(5000);
			} catch (InterruptedException ie){}
			statusPanel.setStatus(false);
		}
		else if (StatusNumber == STATUS_BAD_HOST){
			statusPanel.setStatusText("Could not connect to Host. Check to see if server hostname is correct", Color.red);
			try {
				Thread.sleep(5000);
			} catch (InterruptedException ie){}
			statusPanel.setStatus(false);
		}
		else if (StatusNumber == STATUS_ERROR){
			statusPanel.setStatusText("Error connecting to server", Color.red);
			try {
				Thread.sleep(5000);
			} catch (InterruptedException ie){}
			statusPanel.setStatus(false);
		}
		else if (StatusNumber == STATUS_DISCONNECTED){
			statusPanel.setStatusText("Disconnected from XMPP Server", Color.red);
			try {
				Thread.sleep(5000);
			} catch (InterruptedException ie){}
			statusPanel.setStatus(false);
		}
	}
	
	private void setDisconnectionState(){
		MainMenuPanel m = (MainMenuPanel)PhalanxPanelManager.getInstance().getPanel(MainMenuPanel.NAME);
		m.getServerNodeButton().setEnabled(false);
		m.setConnectionStateButton(false);
	}
	
	private void setConnectionState(){
		MainMenuPanel m = (MainMenuPanel)PhalanxPanelManager.getInstance().getPanel(MainMenuPanel.NAME);
		m.getServerNodeButton().setEnabled(true);
		m.setConnectionStateButton(true);
	}
	
	public boolean getIsConnected(){
		return isConnected;
	}
	
	public ChatManager getChatManager() {
		return xmppCon.getChatManager();
	}
	
	public void disconnect(){
		if (xmppCon != null){
			if (xmppCon.isConnected()){
				xmppCon.disconnect();
			}
		}
	}
}
